/*
 * jxDao Project (2014)
 * 
 * by Denilson Edinaldo Pinto
 * 
 * LGPL
 * Copyright (C) 2014
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.jxDao.dao;

import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jxDao.dao.db.DBInfo;
import org.jxDao.dao.db.DBMS;
import org.jxDao.dao.exception.JXDaoException;
import org.jxUtils.check.ParameterCheck;

/**
 * @author Denilson Edinaldo Pinto
 * @porject jxDao
 * @package org.jxDao.dao
 * @date 23/04/2014 - 16:44:49
 */
public final class DBManager implements Closeable {
	
	private static final Map<Class<?>, GenericDao<? extends Persistable>> DAO_CACHE = new HashMap<>();

	private static boolean validateDatabase = true;
	
	private static boolean showSQL = false;
	
	private final List<Conn> connList = new ArrayList<>();
	
	private DBInfo dbInfo = null;
	
	/**
	 * @param dbInfo
	 * @throws JXDaoException if not possible connect
	 */
	public DBManager(final DBInfo dbInfo) throws JXDaoException {
	
		ParameterCheck.isNull(dbInfo, "dbInfo");
		
		this.dbInfo = dbInfo;
		
		canConnect();
	}
	
	/**
	 * @return true if can connect
	 * @throws JXDaoException
	 *         if can't connect
	 */
	public boolean canConnect() throws JXDaoException {
	
		newConn();
		
		return true;
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see java.io.Closeable#close()
	 */
	@Override
	public void close() throws IOException {
	
		//
		for(final Conn conn : connList) {
			
			conn.close();
		}
	}
	
	/**
	 * @param conn
	 * @throws IOException
	 */
	public void close(final Conn conn) throws IOException {
	
		ParameterCheck.isNull(conn, "conn");
		
		final int index = connList.indexOf(conn);
		
		connList.get(index).close();
		
		connList.remove(index);
	}
	
	/**
	 * This method is equal {@link DBManager#close()}
	 * 
	 * @throws IOException
	 */
	public void closeAll() throws IOException {
	
		close();
	}
	
	/**
	 * @return {@link DBInfo}
	 */
	public DBInfo getDBInfo() {
	
		return dbInfo;
	}
	
	/**
	 * @return {@link DBMS}
	 */
	public DBMS getDBMS() {
	
		return dbInfo.getDBMS();
	}
	
	/**
	 * @return driverName
	 */
	public String getDriverName() {
	
		return dbInfo.getDriver().getName();
	}
	
	/**
	 * autoCommit is true
	 * initConnection is true
	 * 
	 * @return {@link Conn}
	 * @throws JXDaoException
	 */
	public Conn newConn() throws JXDaoException {
	
		return newConn(true);
	}
	
	/**
	 * initConnection is true
	 * 
	 * @param autoCommit
	 * @return {@link Conn}
	 * @throws JXDaoException
	 */
	public Conn newConn(final boolean autoCommit) throws JXDaoException {
	
		final Conn conn = new Conn(getDBInfo(), true, autoCommit);
		
		conn.setManager(this);
		
		connList.add(conn);
		
		return conn;
	}
	
	/**
	 *
	 */
	public static void clearDaoCache() {
	
		getDaoCache().clear();
	}
	
	/**
	 * @param beanClass
	 */
	public static boolean containsDaoInCache(final Class<?> beanClass) {
	
		return getDaoCache().containsKey(beanClass);
	}
	
	/**
	 * @return the DAO_CACHE
	 */
	public static Map<Class<?>, GenericDao<? extends Persistable>> getDaoCache() {
	
		return DAO_CACHE;
	}
	
	/**
	 * @param beanClass
	 * @return the Dao
	 * @return {@link GenericDao}
	 */
	@SuppressWarnings("unchecked")
	public static <TDao> TDao getDaoFromCache(final Class<?> beanClass) {
	
		return (TDao)getDaoCache().get(beanClass);
	}
	
	/**
	 * @return the showSQL
	 */
	public static boolean isShowSQL() {
	
		return showSQL;
	}
	
	/**
	 * @return the validateDatabase
	 */
	public static final boolean isValidateDatabase() {
	
		return validateDatabase;
	}
	
	/**
	 * @param beanClass
	 */
	public static void removeDaoFromCache(final Class<?> beanClass) {
	
		getDaoCache().remove(beanClass);
	}
	
	/**
	 * @param showSQL
	 *        the showSQL to set
	 */
	public static void setShowSQL(final boolean showSQL) {
	
		DBManager.showSQL = showSQL;
	}
	
	/**
	 * @param validateDatabase
	 *        the validateDatabase to set
	 */
	public static final void setValidateDatabase(boolean validateDatabase) {
	
		DBManager.validateDatabase = validateDatabase;
	}
}
